package yartiss.engine.simulation.scheduling.policies.fp;

import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;

import yartiss.engine.simulation.IEnergyProfile;
import yartiss.engine.simulation.ISchedulingPolicy;
import yartiss.engine.simulation.events.EventGenerator;
import yartiss.engine.simulation.scheduling.policies.AbstractMonoProcessorSchedulingPolicy;
import yartiss.engine.simulation.system.ITask;
import yartiss.engine.simulation.system.ITaskSet;
import yartiss.engine.simulation.system.taskset.TaskSetFactory;

/**
 * Preemptive Fixed Priority. When there is not enough energy, the system is
 * paused for x time unit (even if it results in missing a deadline)
 */
public class EHPFP1SchedulingPolicy extends AbstractMonoProcessorSchedulingPolicy  {

	private List<Integer> parameters = new ArrayList<Integer>();
	private long sleepUntil = -1;

	/**
	 * 
	 */
	@Override
	public String getPolicyName() {
		return "EH_PFP_1";
	}

	/**
	 * 
	 */
	@Override
	public void setParameters(List<Integer> parameters) {
		this.parameters = parameters;
	}
	
	@Override
	public List<Integer> getParameters() {
		return parameters;
	}

	/**
	 * 
	 */
	@Override
	public ITaskSet createTaskSet() {
		return TaskSetFactory.getNewInstance("priority");
	}

	/**
	 * 
	 */
	@Override
	public ITask chooseNextTask(ITaskSet taskSet,IEnergyProfile energyProfile, long date, EventGenerator evGen) {

		if (date == 0)
			sleepUntil = -1;

		int x =  this.parameters==null || this.parameters.isEmpty() ? 1 : parameters.get(0);
		x = x == 0 ? 1 : x;

		SortedSet<ITask> activeTasks = taskSet.getActiveTasks(date);

		if (!activeTasks.isEmpty() && (date >= sleepUntil)) {
			ITask first = activeTasks.first();
			long hlcet = energyProfile.howLongCanExecute(first);

			if (hlcet <= 0) {
				sleepUntil = date + x;
				evGen.generateEvent("check_energy_state", activeTasks.first(), sleepUntil, null);
				return null;
			}

			if (hlcet < activeTasks.first().getRemainingCost())
				evGen.generateEvent("check_energy_state", activeTasks.first(), date + hlcet, null);

			return activeTasks.first();
		}

		return null;
	}

	@Override
	public ISchedulingPolicy newInstance() {
		return new EHPFP1SchedulingPolicy();
	}
}
